﻿using System;
using System.Collections;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NetAssist.Collections;
//using System.Collections;

namespace NetAssistTests
{
  [TestClass()]
  public class BufferTests
  {
    [TestMethod()]
    public void BufferConstructorTest()
    {
      Buffer<int> buffer1 = new Buffer<int>(4);
      Assert.IsTrue(buffer1.MaxSize == 4);
      Assert.IsTrue(buffer1.Full == false);
      Assert.IsTrue(buffer1.Empty == true);
      Assert.IsTrue(buffer1.Usage == 0);
      Assert.IsTrue(buffer1.Count == 0);
    }

    [TestMethod()]
    public void BufferResizeTest()
    {
      Buffer<int> buffer1 = new Buffer<int>(5);
      Assert.IsTrue(buffer1.MaxSize == 5);
      Assert.IsTrue(buffer1.Full == false);
      Assert.IsTrue(buffer1.Empty == true);
      Assert.IsTrue(buffer1.Usage == 0);
      Assert.IsTrue(buffer1.Count == 0);

      buffer1.Resize(4);
      Assert.IsTrue(buffer1.MaxSize == 4);
      Assert.IsTrue(buffer1.Full == false);
      Assert.IsTrue(buffer1.Empty == true);
      Assert.IsTrue(buffer1.Usage == 0);
      Assert.IsTrue(buffer1.Count == 0);

      buffer1.Push(1);
      buffer1.Push(2);
      buffer1.Push(3);

      Assert.IsTrue(buffer1.MaxSize == 4);
      Assert.IsTrue(buffer1.Full == false);
      Assert.IsTrue(buffer1.Empty == false);
      Assert.IsTrue(buffer1.Usage == .75);
      Assert.IsTrue(buffer1.Count == 3);

      buffer1.Resize(3);
      Assert.IsTrue(buffer1.MaxSize == 3);
      Assert.IsTrue(buffer1.Full == true);
      Assert.IsTrue(buffer1.Empty == false);
      Assert.IsTrue(buffer1.Usage == 1);
      Assert.IsTrue(buffer1.Count == 3);

      buffer1.Resize(4);
      Assert.IsTrue(buffer1.MaxSize == 4);
      Assert.IsTrue(buffer1.Full == false);
      Assert.IsTrue(buffer1.Empty == false);
      Assert.IsTrue(buffer1.Usage == .75);
      Assert.IsTrue(buffer1.Count == 3);

      try
      {
        buffer1.Resize(2);
        Assert.Fail();
      }
      catch (System.Exception ex)
      {
        Assert.IsTrue(ex.GetType() == typeof(ArgumentOutOfRangeException));
      }
    }

    [TestMethod()]
    public void BufferAccessTest()
    {
      Buffer<int> buffer1 = new Buffer<int>(3);
      buffer1.BufferOverflow += new EventHandler<BufferOverflowEventArgs<int>>(buffer1_BufferOverflow);

      buffer1.Push(1);
      buffer1.Push(2);
      buffer1.Push(3);
      buffer1.Push(4);

      Assert.IsTrue(buffer1.Pop() == 2);
      Assert.IsTrue(buffer1.Peek() == 3);
      Assert.IsTrue(buffer1.Contains(4));

      buffer1.Push(5);
      Assert.IsTrue(buffer1[1] == 4);
      Assert.IsTrue(buffer1[2] == 5);

      try
      {
        int y = buffer1[21];
        Assert.Fail();
      }
      catch (Exception ex)
      {
        Assert.IsTrue(ex.GetType() == typeof(IndexOutOfRangeException));
      }

      try
      {
        int y = buffer1[-1];
        Assert.Fail();
      }
      catch (Exception ex)
      {
        Assert.IsTrue(ex.GetType() == typeof(IndexOutOfRangeException));
      }
    }

    [TestMethod()]
    public void BufferCopyTest()
    {
      Buffer<int> buffer1 = new Buffer<int>(3);
      buffer1.Push(1);
      buffer1.Push(2);
      buffer1.Push(3);

      int[] arr1 = new int[5];
      buffer1.CopyTo(arr1, 1);

      Array arr2 = new int[5];
      buffer1.CopyTo(arr2, 1);

      int[] arr3 = new int[] { 0, 1, 2, 3, 0 };

      Assert.IsTrue(arr1.SequenceEqual(arr3));
      Assert.IsTrue(arr2.OfType<int>().SequenceEqual(arr1));
    }
    
    [TestMethod()]
    public void BufferMiscTest()
    {
      Buffer<int> buffer1 = new Buffer<int>(3);
      buffer1.Push(1);
      buffer1.Push(2);
      buffer1.Push(3);

      Assert.IsTrue(buffer1.SyncRoot == buffer1);
      Assert.IsTrue(buffer1.IsSynchronized == false);

      int idx = 0;
      foreach (var item in (IEnumerable)buffer1)
      {
        idx++;
        Assert.IsTrue((int)item == idx);
      }
    }

    void buffer1_BufferOverflow(object sender, BufferOverflowEventArgs<int> e)
    {
      Assert.IsTrue(e.Item == 1);
    }
  }
}
